/**
 * 高阶函数:
 * 1. 把一个函数当成参数传递给另一个函数
 * 2. 一个函数返回了一个函数
 */

// 1. 参数是函数
function fn(callback) {
    callback();
}

fn(() => console.log(1));

// 2. 返回的是函数
function Fn(x) {
    return function (y) {
        return x + y;
    }
}

console.log(Fn(5)(4));


/**
 * 装饰器: 不改变原来的功能，而是在原有基础上，增加新的功能
 */

function obtainName(x, y) {
    return x + y;
}

function decorator(fn) {
    return function (...args) {
        console.log(`params: ${args}`);
        const result = fn.apply(this, args);
        console.log(`result: ${result}`);
        return result;
    }
}

decorator(obtainName)(1, 2);

console.log('==========================================================');

Function.prototype.around = function (before, after) {
    // 这里的 this 指的是被增强的函数
    const _that = this;
    return function (...args) {
        // 这里的 this 就是 window
        // 前置通知
        before(args);
        // 执行业务逻辑
        const ret = _that(args);
        // 后置通知
        after(ret);
    };
}

function say(param) {
    console.log(`say ${param}`);
    return `say ${param}`;
}


say.around(
    (args) => console.log(`前置通知...拿到参数: ${args}`),
    (ret) => console.log(`后置通知...返回结果: ${ret}`)
)('Hello zs');


console.log('=======================================================================');

// 和上边的是等价的
say.around(
    (args) => console.log(`前置通知...拿到参数: ${args}`),
    (ret) => console.log(`后置通知...返回结果: ${ret}`)
).call(say, 'Hello zs');

console.log('=======================================================================');

Function.prototype.paramsValidate = function () {
    const _that = this;
    return function (...args) {
        for (let i of args) {
            if (!i) {
                console.log('请检查参数');
                return;
            }
        }
        return _that(...args);
    };
}

function calculate(x, y) {
    return x + y;
}

console.log(calculate.paramsValidate().call(calculate, 1, 2));